package org.maven.dependencybrowser.sample;

import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Properties;

import org.codehaus.classworlds.ClassWorld;
import org.codehaus.classworlds.DuplicateRealmException;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.embed.Embedder;
import org.maven.dependencybrowser.controller.ArtifactResolver;
import org.maven.dependencybrowser.implementations.IProgressMeter;
import org.maven.dependencybrowser.implementations.Workspace;
import org.maven.dependencybrowser.implementations.local.LocalDiskRepository;
import org.maven.dependencybrowser.implementations.local.LocalDiskWorkspace;
import org.maven.dependencybrowser.implementations.zip.ZipFileRepository;
import org.maven.dependencybrowser.implementations.zip.ZipFileWorkspace;
import org.maven.dependencybrowser.model.Artifact;
import org.maven.dependencybrowser.model.ArtifactInitialisationException;

/**
 * reference impementation of a command line client. shows how to bootstrap and configure the core implementation 
 */
public class CLIImplementation {

	private static final String KEY_POM = "pom";
	private static final String KEY_TYPE = "type";
	public static final String TYPE_LOCAL = "local";
	private static final String TYPE_ZIP = "zip";

	/**
	 * @deprecated - use gui config org.maven.dependencybrowser.config.Config instead
	 */
	private static final String ARG_REPOSITORY = "--repository=";
	/**
	 * @deprecated - use gui config org.maven.dependencybrowser.config.Config instead
	 */
	private static final String ARG_WORKSPACE = "--workspace=";
	private static final String ARG_SNAPSHOT = "--snapshot=";
	private static final String ARG_POM = "--pom=";
	
	public static void main(String[] args) throws DuplicateRealmException, PlexusContainerException, ComponentLookupException, ArtifactInitialisationException {
		Properties properties = configureFromCommandLine(args);
		Embedder embedder = new Embedder();
		ClassWorld classWorld = new ClassWorld();
		classWorld.newRealm("plexus.core", Thread.currentThread().getContextClassLoader());
		embedder.setProperties(properties);
		embedder.start(classWorld);
		
		// retrieve the required components from plexus 
		Workspace workspace = (Workspace) embedder.lookup(Workspace.ROLE);
		ArtifactResolver artifactResolver = (ArtifactResolver) embedder.lookup(ArtifactResolver.ROLE);
				
		if (TYPE_LOCAL.equals(properties.get(KEY_TYPE))) {
			LocalDiskWorkspace localDiskWorkspace = (LocalDiskWorkspace) workspace;
			localDiskWorkspace.loadRootPom(new File(properties.getProperty(KEY_POM)));
		}
		if (TYPE_ZIP.equals(properties.get(KEY_TYPE))) {
			ZipFileWorkspace localDiskWorkspace = (ZipFileWorkspace) workspace;
			localDiskWorkspace.loadRootPom(properties.getProperty(KEY_POM));
		}
		
		workspace.getRoot().resolveDependencies(artifactResolver, new IProgressMeter() {

			public void resolving(Artifact artifact) {
				System.out.println("resolving: " + artifact.getId());
			}
			
		});
		
		System.out.println("======== dependency tree ===========");
		iterateTree(workspace.getRoot(), 0);
		
		embedder.stop();
	}
	
	private static void iterateTree(Artifact pom, int depth) {
		char[] padding = new char[depth * 2];
		Arrays.fill(padding, " ".charAt(0));
		System.out.println(new String(padding) + pom.getId());
		for (Iterator iter = pom.getDependencies().iterator(); iter.hasNext();) {
			Artifact dependency = (Artifact) iter.next();
			iterateTree(dependency, depth + 1);
		}
	}
	
	private static Properties configureFromCommandLine(String[] args) {
		Properties properties = new Properties();
		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith(ARG_REPOSITORY)) {
				setRepositoryType(properties, TYPE_LOCAL);
				properties.setProperty(LocalDiskRepository.KEY_LOCAL_REPO_PATH, args[i].substring(ARG_REPOSITORY.length()));
			}
			if (args[i].startsWith(ARG_WORKSPACE)) {
				setRepositoryType(properties, TYPE_LOCAL);
				properties.setProperty(LocalDiskWorkspace.KEY_WORKSPACE_PATH, args[i].substring(ARG_WORKSPACE.length()));
			}
			if (args[i].startsWith(ARG_SNAPSHOT)) {
				setRepositoryType(properties, TYPE_ZIP);
				properties.setProperty(ZipFileRepository.KEY_ZIPFILE_PATH, args[i].substring(ARG_SNAPSHOT.length()));
				properties.setProperty(ZipFileWorkspace.KEY_ZIPFILE_PATH, args[i].substring(ARG_SNAPSHOT.length()));
			}
			if (args[i].startsWith(ARG_POM)) {
				properties.setProperty(KEY_POM, args[i].substring(ARG_POM.length()));
			}
		}
		return properties;
	}
	
	private static void setRepositoryType(Properties properties, String type) {
		if (properties.get(KEY_TYPE) == null || properties.get(KEY_TYPE).equals(type)) {
			properties.setProperty(KEY_TYPE, type);
		} else {
			throw new IllegalArgumentException("Cannot overwrite configuration type " + properties.get(KEY_TYPE) + " with type " + type);
		}
	}

}
